/**
 * $Revision: 1.1 $
 * $Date: 2010/06/28 07:03:25 $
 *
 * Copyright (C) 2006 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Lesser Public License (LGPL),
 * a copy of which is included in this distribution.
 */

package cn.newgrand.netcall.offlinefiletransfer.ui;

import org.jivesoftware.Spark;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smackx.filetransfer.FileTransfer;
import org.jivesoftware.smackx.filetransfer.FileTransfer.Error;
import org.jivesoftware.smackx.filetransfer.FileTransfer.Status;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.FileDragLabel;
import org.jivesoftware.spark.ui.ContactItem;
import org.jivesoftware.spark.ui.ContactList;
import org.jivesoftware.spark.util.ByteFormat;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.spark.util.log.Log;

import cn.newgrand.common.StringUtil;
import cn.newgrand.smackx.packet.AppSysIQ;
import cn.newgrand.smackx.packet.FileTransferCancel;
import cn.newgrand.netcall.offlinefiletransfer.EmailSendingHelper;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;

public class SendMessage extends JPanel {
    private FileDragLabel imageLabel = new FileDragLabel();
    private JLabel titleLabel = new JLabel();
    private JLabel fileLabel = new JLabel();

    private TransferButton cancelButton = new TransferButton();
    private TransferButton retryButton = new TransferButton();
    private File fileToSend;
    private JProgressBar progressBar = new JProgressBar();
    private org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer transfer;
    
    private JProgressBar offlineProgressBar = new JProgressBar();
    private TransferButton offlineSendingButton = new TransferButton();
    private TransferButton offlineRetryButton = new TransferButton();
    private TransferButton offlineCancelButton = new TransferButton();
    private cn.newgrand.smackx.offlinefiletransfer.OutgoingFileTransfer offlineTransfer;
    
    private TransferButton emailSendingButton = new TransferButton();
    private TransferButton emailRetryButton = new TransferButton();
    private TransferButton emailCancelButton = new TransferButton();
    private JLabel emailProgressBar = new JLabel();
    private org.jivesoftware.smackx.filetransfer.FileTransferManager transferManager;
    private cn.newgrand.smackx.offlinefiletransfer.FileTransferManager offlineTransferManager;
    private String fullJID;
    private String nickname;

    private boolean cancelOnline = false;
    
    private boolean isOffline = false;
    
    public SendMessage(final boolean isOffline) {
        setLayout(new GridBagLayout());

        setBackground(new Color(250, 249, 242));
        add(imageLabel, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));

        add(titleLabel, new GridBagConstraints(1, 0, 3, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
        titleLabel.setFont(new Font("Dialog", Font.BOLD, 12));
        titleLabel.setForeground(new Color(211, 174, 102));
        add(fileLabel, new GridBagConstraints(1, 1, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0));

        cancelButton.setText(Res.getString("cancel"));
        retryButton.setText(Res.getString("retry"));

        offlineCancelButton.setText("取消离线文件");
        offlineRetryButton.setText("重发离线文件");
        offlineSendingButton.setText("发送离线文件");
        
        emailSendingButton.setText("发送Email");
        emailCancelButton.setText("取消Email");
        emailRetryButton.setText("重发Email");
        
        add(cancelButton, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        add(retryButton, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        
        add(offlineCancelButton, new GridBagConstraints(2, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        add(offlineRetryButton, new GridBagConstraints(2, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        add(offlineSendingButton, new GridBagConstraints(2, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        add(emailSendingButton, new GridBagConstraints(3, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        add(emailRetryButton, new GridBagConstraints(3, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        add(emailCancelButton, new GridBagConstraints(3, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        
        
        emailProgressBar.setIcon(SparkRes.getImageIcon(SparkRes.EMAIL_SENDING));
        add(emailProgressBar, new GridBagConstraints(1, 1, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0));
        
        this.isOffline = isOffline;
        if(isOffline){
        	cancelButton.setVisible(false);
        }
        retryButton.setVisible(false);
        offlineRetryButton.setVisible(false);
        offlineCancelButton.setVisible(false);
        emailRetryButton.setVisible(false);
        emailCancelButton.setVisible(false);
        emailProgressBar.setVisible(false);
        
        retryButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    File file = new File(transfer.getFilePath());
                    transfer = transferManager.createOutgoingFileTransfer(fullJID);
                    transfer.sendFile(file, "Sending");
                }
                catch (XMPPException e1) {
                    Log.error(e1);
                }
                sendFile(transfer, transferManager, fullJID, nickname,offlineTransferManager);
            }
        });
        
        offlineSendingButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                File file = fileToSend;
                try {
//                	//fangt 发送离线前先删除对方未开始传输的panel
//                	FileTransferCancel iq = new FileTransferCancel();
//                	iq.setTo(fullJID);
//                	iq.setFrom(SparkManager.getConnection().getUser());
//                	iq.setType(Type.GET);
//                	iq.setCancel(true);
//                	iq.setFileName(file.getName());
//                	PacketFilter filter = new PacketIDFilter(iq.getPacketID());
//                	PacketCollector collector = SparkManager.getConnection().createPacketCollector(filter);
//                	SparkManager.getConnection().sendPacket(iq);
//                	FileTransferCancel ret = (FileTransferCancel)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
                	
                    offlineTransfer = offlineTransferManager.createOutgoingFileTransfer(fullJID);
                    offlineTransfer.sendFile(file, "Sending",true,SparkManager.getConnection(),fullJID);
                    offlineSendingButton.setVisible(false);
                }
                catch (XMPPException e1) {
                    Log.error(e1);
                }
                if(!isOffline){
	                try {
						sendOfflineFile(file, offlineTransfer, offlineTransferManager, fullJID, nickname,false);
					} catch (XMPPException e1) {
						// TODO Auto-generated catch block
						Log.error(e1);
					}
                }
            }
        });
        
        offlineRetryButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                File file = fileToSend;
                try {
                    offlineTransfer = offlineTransferManager.createOutgoingFileTransfer(fullJID);
                    offlineTransfer.sendFile(file, "Sending",true);
                }
                catch (XMPPException e1) {
                    Log.error(e1);
                }
                try {
					sendOfflineFile(file,offlineTransfer, offlineTransferManager, fullJID, nickname,false);
				} catch (XMPPException e1) {
					// TODO Auto-generated catch block
					Log.error(e1);
				}
            }
        });
        
        emailSendingButton.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				sendEmailFile();
			}
        	
        });
        
        emailRetryButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
				sendEmailFile();
            }
        });
        
        emailCancelButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            	//emailRetryButton
            }
        });
        
        cancelButton.setForeground(new Color(73, 113, 196));
        cancelButton.setFont(new Font("Dialog", Font.BOLD, 12));
        cancelButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));

        retryButton.setForeground(new Color(73, 113, 196));
        retryButton.setFont(new Font("Dialog", Font.BOLD, 12));
        retryButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));

        offlineRetryButton.setForeground(new Color(73, 113, 196));
        offlineRetryButton.setFont(new Font("Dialog", Font.BOLD, 12));
        offlineRetryButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));

        offlineSendingButton.setForeground(new Color(73, 113, 196));
        offlineSendingButton.setFont(new Font("Dialog", Font.BOLD, 12));
        offlineSendingButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));
        
        offlineCancelButton.setForeground(new Color(73, 113, 196));
        offlineCancelButton.setFont(new Font("Dialog", Font.BOLD, 12));
        offlineCancelButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));

        emailSendingButton.setForeground(new Color(73, 113, 196));
        emailSendingButton.setFont(new Font("Dialog", Font.BOLD, 12));
        emailSendingButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));
        
        emailRetryButton.setForeground(new Color(73, 113, 196));
        emailRetryButton.setFont(new Font("Dialog", Font.BOLD, 12));
        emailRetryButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));

        emailCancelButton.setForeground(new Color(73, 113, 196));
        emailCancelButton.setFont(new Font("Dialog", Font.BOLD, 12));
        emailCancelButton.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(73, 113, 196)));

        setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.white));
    }

    public void setFileToSend(File file){
    	this.fileToSend = file;
    }
    
    public void setFullJID(String fullJID){
    	this.fullJID = fullJID;
    }
    
    public void sendEmailFile() {
		// TODO Auto-generated method stub
		//发送离线文件时，无法发送文件和邮件
    	final String email = SparkManager.getVCardManager().reloadVCard(fullJID).getEmailHome();
    	
    	if(this.fileToSend==null||StringUtil.isEmpty(email)){
    		JOptionPane.showMessageDialog(this, "对方未设置Email");
    		return;
    	}
    	
		emailRetryButton.setVisible(true);
		emailSendingButton.setVisible(false);
		emailCancelButton.setVisible(false);
//		offlineCancelButton.setEnabled(true);
//		cancelButton.setEnabled(false);
//		offlineSendingButton.setEnabled(false);
		offlineSendingButton.setVisible(false);
		offlineCancelButton.setVisible(false);
		offlineRetryButton.setVisible(false);
		cancelButton.setVisible(false);
		retryButton.setVisible(false);
		
		progressBar.setVisible(false);
		offlineProgressBar.setVisible(false);
		
//        if(transfer!=null&&(!transfer.getStatus().equals(org.jivesoftware.smackx.filetransfer.FileTransfer.Status.cancelled)||!transfer.getStatus().equals(org.jivesoftware.smackx.filetransfer.FileTransfer.Status.error))){
//        	transfer.cancel();
//        }
//        if(offlineTransfer!=null&&(!offlineTransfer.getStatus().equals(cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.cancelled)||!offlineTransfer.getStatus().equals(cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.error))){
//        	offlineTransfer.cancel();
//        }
       
        IQ packet = new AppSysIQ();
        packet.setTo("integration."+SparkManager.getConnection().getServiceName());
        packet.setFrom(SparkManager.getConnection().getUser());

        PacketFilter filter = new PacketIDFilter(packet.getPacketID());
        PacketCollector collector = SparkManager.getConnection().createPacketCollector(filter);
        SparkManager.getConnection().sendPacket(packet);
        Packet packetTemp = collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
        if(packetTemp==null||packetTemp.getError()!=null){
        	titleLabel.setText("失败发送Email到"+nickname);
        	return;
        }
        final AppSysIQ result =(AppSysIQ)packetTemp ;
        
        if(result==null||result.getType().equals(Type.ERROR)||result.getProperty("integration.ng.app.email.url")==null||result.getProperty("integration.ng.app.email.method")==null){
        	titleLabel.setText("失败发送Email到"+nickname);
        	return;
        }
        
//        Thread transferThread = new Thread(new Runnable() {
//			public void run() {
//			}
//
//		}, "Email File Transfer");
//		transferThread.start();
        
        
        SwingWorker worker = new SwingWorker() {
            public Object construct() {
            	fileLabel.setVisible(false);
            	emailProgressBar.setVisible(true);
        		titleLabel.setText("正在发送邮件给"+nickname);
		        EmailSendingHelper.sendEmail(result.getProperty("integration.ng.app.email.url"), fileToSend,SparkManager.getConnection().getUser(),fullJID,email,result.getProperty("integration.ng.app.email.method"));
                return "";
            }

            public void finished() {
            	emailProgressBar.setVisible(false);
            	emailRetryButton.setVisible(false);
            	fileLabel.setVisible(true);
        		titleLabel.setText("发送Email到"+nickname);
            }
        };

        worker.start();
	}

	public void sendFile(final org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer transfer, org.jivesoftware.smackx.filetransfer.FileTransferManager transferManager, final String jid, final String nickname, cn.newgrand.smackx.offlinefiletransfer.FileTransferManager offlineTransferManager) {
        this.transferManager = transferManager;

        //同时支持离线
        this.offlineTransferManager = offlineTransferManager;
        
        cancelButton.setVisible(true);
        retryButton.setVisible(false);
        this.fullJID = jid;
        this.nickname = nickname;

        this.transfer = transfer;
        String fileName = transfer.getFileName();
        long fileSize = transfer.getFileSize();
        ByteFormat format = new ByteFormat();
        String text = format.format(fileSize);

        fileToSend = new File(transfer.getFilePath());
        imageLabel.setFile(fileToSend);

        fileLabel.setText(fileName + " (" + text + ")");

        ContactList contactList = SparkManager.getWorkspace().getContactList();
        ContactItem contactItem = contactList.getContactItemByJID(jid);

        titleLabel.setText(Res.getString("message.transfer.waiting.on.user", contactItem.getDisplayName()));

        if (isImage(fileName)) {
            try {
                URL imageURL = new File(transfer.getFilePath()).toURL();
                ImageIcon image = new ImageIcon(imageURL);
                image = GraphicUtils.scaleImageIcon(image, 64, 64);
                imageLabel.setIcon(image);
            }
            catch (MalformedURLException e) {
                Log.error("Could not locate image.", e);
                imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.DOCUMENT_INFO_32x32));
            }
        }
        else {
            File file = new File(transfer.getFilePath());
            Icon icon = GraphicUtils.getIcon(file);
            imageLabel.setIcon(icon);
        }
        cancelButton.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent mouseEvent) {
                transfer.cancel();
            }
        });

        cancelButton.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR));

            }

            public void mouseExited(MouseEvent e) {
                cancelButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        });


        progressBar.setMaximum((int)fileSize);
        progressBar.setVisible(false);
        progressBar.setStringPainted(true);
        add(progressBar, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0));


        SwingWorker worker = new SwingWorker() {
            public Object construct() {
                while (true) {
                    try {
                        Thread.sleep(10);
                        FileTransfer.Status status = transfer.getStatus();
                        if (status == Status.error ||
                            status == Status.complete || status == Status.cancelled ||
                            status == Status.refused) {
                            break;
                        }
                        updateBar(transfer, nickname);
                    }
                    catch (InterruptedException e) {
                        Log.error("Unable to sleep thread.", e);
                    }

                }
                return "";
            }

            public void finished() {
                updateBar(transfer, nickname);
                if(cancelOnline){
                    retryButton.setVisible(false);
                	cancelOnline = false;
                }
            }
        };

        worker.start();

        makeClickable(imageLabel);
        makeClickable(titleLabel);
    }

//	public void sendOfflineFile() throws XMPPException {
//
//		offlineTransfer.sendFile(this.fileToSend, "sending file",true);
//        
//        cancelButton.setVisible(true);
//        retryButton.setVisible(false);
//        offlineSendingButton.setVisible(false);
//        
//        String fileName = offlineTransfer.getFileName();
//        long fileSize = offlineTransfer.getFileSize();
//        ByteFormat format = new ByteFormat();
//        String text = format.format(fileSize);
//
//        imageLabel.setFile(fileToSend);
//
//        fileLabel.setText(fileName + " (" + text + ")");
//
//        ContactList contactList = SparkManager.getWorkspace().getContactList();
//        ContactItem contactItem = contactList.getContactItemByJID(this.fullJID);
//
//        titleLabel.setText(Res.getString("message.transfer.waiting.on.user", contactItem.getDisplayName()));
//
//        if (isImage(fileName)) {
//            try {
//                URL imageURL = new File(offlineTransfer.getFilePath()).toURL();
//                ImageIcon image = new ImageIcon(imageURL);
//                image = GraphicUtils.scaleImageIcon(image, 64, 64);
//                imageLabel.setIcon(image);
//            }
//            catch (MalformedURLException e) {
//                Log.error("Could not locate image.", e);
//                imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.DOCUMENT_INFO_32x32));
//            }
//        }
//        else {
//            File file = new File(offlineTransfer.getFilePath());
//            Icon icon = GraphicUtils.getIcon(file);
//            imageLabel.setIcon(icon);
//        }
//        cancelButton.addMouseListener(new MouseAdapter() {
//            public void mouseClicked(MouseEvent mouseEvent) {
//            	offlineTransfer.cancel();
//            }
//        });
//
//        cancelButton.addMouseListener(new MouseAdapter() {
//            public void mouseEntered(MouseEvent e) {
//                cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
//
//            }
//
//            public void mouseExited(MouseEvent e) {
//                cancelButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
//            }
//        });
//
//
//        progressBar.setMaximum((int)fileSize);
//        progressBar.setVisible(false);
//        progressBar.setStringPainted(true);
//        add(progressBar, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0));
//
//
//        SwingWorker worker = new SwingWorker() {
//            public Object construct() {
//                while (true) {
//                    try {
//                        Thread.sleep(10);
//                        FileTransfer.Status status = offlineTransfer.getStatus();
//                        if (status == Status.error ||
//                            status == Status.complete || status == Status.cancelled ||
//                            status == Status.refused) {
//                            break;
//                        }
//                        updateBar(transfer, nickname);
//                    }
//                    catch (InterruptedException e) {
//                        Log.error("Unable to sleep thread.", e);
//                    }
//
//                }
//                return "";
//            }
//
//            public void finished() {
//                updateBar(offlineTransfer, nickname);
//            }
//        };
//
//        worker.start();
//
//        //makeClickable(imageLabel);
//        //makeClickable(titleLabel);
//    }
	
	public void sendOfflineFile(File transferFile,final cn.newgrand.smackx.offlinefiletransfer.OutgoingFileTransfer transfer, cn.newgrand.smackx.offlinefiletransfer.FileTransferManager transferManager, final String jid, final String nickname,boolean isInitial) throws XMPPException {
		this.offlineTransferManager = transferManager;
		this.offlineTransfer = transfer;
        fileToSend = transferFile;//必须先send文件时再show，应为send时会setfileinfo
        
		//发送离线文件时，无法发送文件和邮件
		emailSendingButton.setEnabled(isInitial);//由于该函数会在两种情况下被调，所以isInitial true表示外部构建发送面板是调用，false表示内部重试调用
		cancelButton.setEnabled(isInitial);
		progressBar.setVisible(false);
        titleLabel.setText("发送离线文件到"+nickname);
        if(this.transfer!=null&&(!this.transfer.getStatus().equals(cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.cancelled)||!this.transfer.getStatus().equals(cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.error))){
        	this.transfer.cancel();
        	this.cancelOnline = true;
        }
        
        this.fullJID = jid;
        this.nickname = nickname;
        
		//offlineTransfer.sendFile(transferFile, "sending file",true);
//        if(!isOffline){
//        	cancelButton.setVisible(true);
//        }
        offlineCancelButton.setVisible(!isInitial);
//        retryButton.setVisible(false);
        offlineSendingButton.setVisible(isInitial);
        offlineRetryButton.setVisible(false);
        
        String fileName = fileToSend.getName();
        long fileSize = fileToSend.length();
        ByteFormat format = new ByteFormat();
        String text = format.format(fileSize);
        
        //fileToSend = new File(this.offlineTransfer.getFilePath());
        imageLabel.setFile(fileToSend);

        fileLabel.setText(fileName + " (" + text + ")");

        ContactList contactList = SparkManager.getWorkspace().getContactList();
        ContactItem contactItem = contactList.getContactItemByJID(this.fullJID);

        titleLabel.setText(Res.getString("message.transfer.waiting.on.user", contactItem.getDisplayName()));

        if (isImage(fileName)) {
            try {
                URL imageURL = fileToSend.toURL();
                ImageIcon image = new ImageIcon(imageURL);
                image = GraphicUtils.scaleImageIcon(image, 64, 64);
                imageLabel.setIcon(image);
            }
            catch (MalformedURLException e) {
                Log.error("Could not locate image.", e);
                imageLabel.setIcon(SparkRes.getImageIcon(SparkRes.DOCUMENT_INFO_32x32));
            }
        }
        else {
            //File file = new File(this.offlineTransfer.getFilePath());
            Icon icon = GraphicUtils.getIcon(fileToSend);
            imageLabel.setIcon(icon);
        }
        offlineCancelButton.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent mouseEvent) {
            	offlineTransfer.cancel();
            }
        });

        offlineCancelButton.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
            	offlineCancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR));

            }

            public void mouseExited(MouseEvent e) {
            	offlineCancelButton.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        });

        progressBar.setVisible(false);
        offlineProgressBar.setMaximum((int)fileSize);
        offlineProgressBar.setVisible(false);
        offlineProgressBar.setStringPainted(true);
        add(offlineProgressBar, new GridBagConstraints(1, 2, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 150, 0));


        SwingWorker worker = new SwingWorker() {
            public Object construct() {
                while (true) {
                    try {
                        Thread.sleep(10);
                        cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status status = offlineTransfer.getStatus();
                        if (status == cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.error ||
                            status == cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.complete || status == cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.cancelled ||
                            status == cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.refused) {
                            break;
                        }
                        updateOfflineBar(offlineTransfer, nickname);
                    }
                    catch (InterruptedException e) {
                        Log.error("Unable to sleep thread.", e);
                    }

                }
                return "";
            }

            public void finished() {
            	updateOfflineBar(offlineTransfer, nickname);
            }
        };

        worker.start();

        //makeClickable(imageLabel);
        //makeClickable(titleLabel);
    }
    
    private void makeClickable(final JLabel label) {
        label.setToolTipText(Res.getString("message.click.to.open"));

        label.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                openFile(fileToSend);
            }

            public void mouseEntered(MouseEvent e) {
                label.setCursor(new Cursor(Cursor.HAND_CURSOR));

            }

            public void mouseExited(MouseEvent e) {
                label.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        });
    }

    private void openFile(File downloadedFile) {
        try {
            if (!Spark.isMac()) {
                boolean opened = SparkManager.getNativeManager().openFile(downloadedFile);
                if (!opened) {
                    JOptionPane.showMessageDialog(this, Res.getString("title.error"), "No application associated with file type.", JOptionPane.ERROR_MESSAGE);
                }
            }
            else if (Spark.isMac()) {
                Runtime.getRuntime().exec("open " + downloadedFile.getCanonicalPath());
            }
        }
        catch (IOException e1) {
            Log.error("Exception occured while opening file.", e1);
        }
    }

    private void updateBar(final org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer transfer, String nickname) {
        FileTransfer.Status status = transfer.getStatus();
        if (status == Status.negotiating_stream) {
            titleLabel.setText(Res.getString("message.negotiation.file.transfer", nickname));
        }
        else if (status == Status.error) {
            if (transfer.getException() != null) {
                Log.error("Error occured during file transfer.", transfer.getException());
            }
            progressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.unable.to.send.file", nickname));
            cancelButton.setVisible(false);
            retryButton.setVisible(true);
            showAlert(true);
        }
        else if (status == Status.in_progress) {
        	//如果开始传输数据，则禁止发送离线文件
        	offlineSendingButton.setEnabled(false);
        	emailSendingButton.setEnabled(false);
        	
            titleLabel.setText(Res.getString("message.sending.file.to", nickname));
            showAlert(false);
            if (!progressBar.isVisible()) {
                progressBar.setVisible(true);
            }
            progressBar.setValue((int)transfer.getBytesSent());

            ByteFormat format = new ByteFormat();
            String bytesSent = format.format(transfer.getBytesSent());
            progressBar.setString(bytesSent + " sent");
        }
        else if (status == Status.complete) {
            progressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.you.have.sent", nickname));
            cancelButton.setVisible(false);
            showAlert(true);
        }
        else if (status == Status.cancelled) {
            progressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.file.transfer.canceled"));
            cancelButton.setVisible(false);
            retryButton.setVisible(true);
            showAlert(true);
        }
        else if (status == Status.refused) {
            progressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.file.transfer.rejected", nickname));
            cancelButton.setVisible(false);
            retryButton.setVisible(true);
            showAlert(true);
        }

    }

    private void updateOfflineBar(final cn.newgrand.smackx.offlinefiletransfer.OutgoingFileTransfer transfer, String nickname) {
    	cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status status = offlineTransfer.getStatus();
        if (status == cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.negotiating_stream) {
            titleLabel.setText(Res.getString("message.negotiation.file.transfer", nickname));
        }
        else if (status == cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.error) {
            if (transfer.getException() != null) {
                Log.error("Error occured during file transfer.", transfer.getException());
            }
            offlineProgressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.unable.to.send.file", nickname));
            offlineCancelButton.setVisible(false);
            offlineRetryButton.setVisible(true);
            showAlert(true);
        }
        else if (status == cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.in_progress) {
            titleLabel.setText(Res.getString("message.sending.file.to", nickname));
            showAlert(false);
            if (!offlineProgressBar.isVisible()) {
            	offlineProgressBar.setVisible(true);
            }
            offlineProgressBar.setValue((int)transfer.getBytesSent());

            ByteFormat format = new ByteFormat();
            String bytesSent = format.format(transfer.getBytesSent());
            offlineProgressBar.setString(bytesSent + " sent");
        }
        else if (status == cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.complete) {
        	offlineProgressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.you.have.sent", nickname));
            offlineCancelButton.setVisible(false);
            showAlert(true);
        }
        else if (status == cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.cancelled) {
        	offlineProgressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.file.transfer.canceled"));
            offlineCancelButton.setVisible(false);
            offlineRetryButton.setVisible(true);
            showAlert(true);
        }
        else if (status == cn.newgrand.smackx.offlinefiletransfer.FileTransfer.Status.refused) {
        	offlineProgressBar.setVisible(false);
            titleLabel.setText(Res.getString("message.file.transfer.rejected", nickname));
            offlineCancelButton.setVisible(false);
            offlineRetryButton.setVisible(true);
            showAlert(true);
        }

    }
    
    private class TransferButton extends JButton {

        public TransferButton() {
            decorate();
        }

        /**
         * Create a new RolloverButton.
         *
         * @param text the button text.
         * @param icon the button icon.
         */
        public TransferButton(String text, Icon icon) {
            super(text, icon);
            decorate();
        }


        /**
         * Decorates the button with the approriate UI configurations.
         */
        private void decorate() {
            setBorderPainted(false);
            setOpaque(true);

            setContentAreaFilled(false);
            setMargin(new Insets(1, 1, 1, 1));
        }

    }

    private boolean isImage(String fileName) {
        fileName = fileName.toLowerCase();

        String[] imageTypes = {"jpeg", "gif", "jpg", "png"};
        for (String imageType : imageTypes) {
            if (fileName.endsWith(imageType)) {
                return true;
            }
        }

        return false;
    }

    private void showAlert(boolean alert) {
        if (alert) {
            titleLabel.setForeground(new Color(211, 174, 102));
            setBackground(new Color(250, 249, 242));
        }
        else {
            setBackground(new Color(239, 245, 250));
            titleLabel.setForeground(new Color(65, 139, 179));
        }
    }

    public void cancelTransfer() {
        if (transfer != null) {
            transfer.cancel();
        }
    }
    
    public void cancelOfflineTransfer() {
        if (offlineTransfer != null) {
        	offlineTransfer.cancel();
        }
    }
}
